/* (C) C.D.F. Miller, Heriot-Watt University, March 1984
 *
 *	Permission is hereby given to reproduce or modify this
 *	software freely, provided that this notice be retained,
 *	and that no use be made of the software for commercial
 *	purposes without the express written permission of the
 *	author.
 */

#include	<lbl.h>
#include	<ctype.h>
#include        <string.h>
#include        <err.h>
#include        "find.h"
#include        "rescan.h"
#include	"externs.h"

void    doreplace(void);
static void domagic(void);
static void getword(char *buffer);

static int translate = 1;

void
rescan()
{
	int  c;

	/*
	 * Keep tempfile, delimiter and translate flag in registers to speed
	 * up this routine; the last two need to be reloaded after and only
	 * after calls to domagic()
	 */
	FILE *tf = tempfile;
	int  dlm = delimiter;
	int  tr = translate;

	while ((c = getc(tf)) != EOF) {
		if (c == MAGIC1) {
			if ((c = getc(tf)) == MAGIC2) {
				domagic();
				dlm = delimiter;
				tr = translate;
				continue;
			}
			else
				ungetc(c, tf);
		}
		if (c == dlm && tr) {
			doreplace();
			continue;
		}
		if (c == '\n')
			fileline++;
		putchar(c);
	}
}

void
domagic()
{
	int     c;
	static char buffer[BUFSIZ];

	switch (getc(tempfile)) {
	case M_DELIM:
		c = getc(tempfile);
		if (c == '\n')
			translate = 0;
		else {
			translate = 1;
			delimiter = (char) c;
			getc(tempfile);
		}
		break;
	case M_FILE:
		if (fgets(buffer, BUFSIZ, tempfile) == NULL)
			buffer[0] = '\0';
		else
			buffer[strlen(buffer) - 1] = '\0';
		filename = buffer;
		fileline = 1;
		break;
	}
}

void
doreplace()
{
	int  c;
	char    type_name[BUFSIZ];
	char    labelname[BUFSIZ];
	Type *tp;
	Label *lp;

	/*
	 * <delimiter><delimiter> gives <delimiter> as output
	 */
	if ((c = getc(tempfile)) == delimiter) {
		putchar(delimiter);
		return;
	}
	ungetc(c, tempfile);
	getword(type_name);
	getword(labelname);
	if ((c = getc(tempfile)) != delimiter) {
		warnx("%smalformed label reference", maybe_loc());
		while (c != delimiter) {
			if (c == EOF || c == '\n')
				break;
			c = getc(tempfile);
		}
		return;
	}
	if ((tp = findtype(type_name, 0)) == NULL) {
		warnx("%sundefined type '%s'", maybe_loc(), type_name);
		printf("<<%s %s>>", type_name, labelname);
		return;
	}
	if ((lp = tp->findlabel(labelname)) == NULL) {
		warnx("%sundefined label '%s'", maybe_loc(), labelname);
		printf("<<%s %s>>", type_name, labelname);
		return;
	}
	lp->print(stdout);
}

void
getword(char *buffer)
{
	int  c;
	int  dlm = delimiter;
	FILE *tf = tempfile;

	c = getc(tf);
	while (isspace(c))
		c = getc(tf);
	while (c != dlm && !isspace(c) && c != '\n' && c != EOF) {
		*buffer++ = (char) c;
		c = getc(tf);
	}
	*buffer = '\0';
	if (!isspace(c) && c != EOF)
		ungetc(c, tf);
}
